<template>
  <div class="novel-ai-chat">
    <div class="chat-header">
      <h3>{{ title }}</h3>
      <div class="chat-actions">
        <el-tooltip content="清空对话历史" placement="top">
          <el-button size="small" circle plain type="info" @click="confirmClearHistory">
            <el-icon><Delete /></el-icon>
          </el-button>
        </el-tooltip>
      </div>
    </div>
    <div class="chat-messages" ref="messagesRef">
      <div v-for="(message, index) in messages" :key="index"
           :class="['message', message.role === 'user' ? 'user-message' : 'ai-message']">
        <div class="message-avatar">
          <el-avatar :size="36" :icon="message.role === 'user' ? UserFilled : Monitor" 
            :class="message.role === 'user' ? 'user-avatar' : 'ai-avatar'" />
        </div>
        <div class="message-content">
          <div class="message-text" v-if="message.role === 'user'">{{ message.content }}</div>
          <div class="message-text" v-else v-html="formatMessage(message.content)"></div>
          <div class="message-time">{{ parseTime(message.time) }}</div>
        </div>
      </div>
      <div v-if="isStreaming" class="message ai-message">
        <div class="message-avatar">
          <el-avatar :size="36" :icon="Monitor" class="ai-avatar" />
        </div>
        <div class="message-content">
          <div class="message-text" v-html="formatMessage(currentStreamContent)"></div>
          <div class="message-typing" v-if="!currentStreamContent">
            <span class="typing-dot"></span>
            <span class="typing-dot"></span>
            <span class="typing-dot"></span>
          </div>
          <div class="message-time">{{ parseTime(new Date()) }}</div>
        </div>
      </div>
    </div>
    <div class="chat-input">
      <el-input
        v-model="inputMessage"
        type="textarea"
        :rows="3"
        :placeholder="placeholder"
        @keyup.enter.ctrl="sendMessage"
        :disabled="isStreaming"
      />
      <div class="input-actions">
        <div class="left-actions">
          <el-switch
            :model-value="enableContext"
            @update:model-value="handleContextChange"
            active-text="上下文"
            inactive-text="上下文"
            active-color="#13ce66"
            size="small"
          />
          <el-tooltip
            content="启用上下文后，AI将能看到之前的对话历史，有助于保持对话的连贯性。禁用上下文则每次对话都是独立的。"
            placement="top"
          >
            <el-icon class="help-icon"><QuestionFilled /></el-icon>
          </el-tooltip>
          
          <!-- 额外按钮 -->
          <template v-for="(button, index) in extraButtons" :key="index">
            <el-button 
              size="small" 
              type="info" 
              plain
              @click="button.onClick && button.onClick(getLastAiMessage())"
            >
              {{ button.text }}
            </el-button>
          </template>
        </div>
        <div class="right-actions">
          <el-button type="danger" v-if="isStreaming" @click="emitAbort">
            <el-icon><CircleCloseFilled /></el-icon> 终止
          </el-button>
          <el-button type="primary" @click="sendMessage" :loading="loading" :disabled="isStreaming">
            <el-icon><Position /></el-icon> 发送
          </el-button>
          <span class="input-tip">按 Ctrl + Enter 发送</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { QuestionFilled, Delete, Monitor, UserFilled, CircleCloseFilled, Position } from '@element-plus/icons-vue'
import { parseTime } from '@/utils/ruoyi'

const props = defineProps({
  title: {
    type: String,
    required: true
  },
  placeholder: {
    type: String,
    default: '请输入您的要求...'
  },
  loading: {
    type: Boolean,
    default: false
  },
  enableContext: {
    type: Boolean,
    default: true
  },
  maxContextMessages: {
    type: Number,
    default: 10
  },
  extraButtons: {
    type: Array,
    default: () => []
  }
})

const emit = defineEmits(['send', 'context-change', 'abort'])

const messageHistory = ref([])
const messages = ref([])
const inputMessage = ref('')
const messagesRef = ref(null)
const isStreaming = ref(false)
const currentStreamContent = ref('')

const getContextMessages = () => {
  if (!props.enableContext) {
    return messages.value.slice(-1)
  }
  
  const recentMessages = messages.value.slice(-props.maxContextMessages)
  return recentMessages
}

const formatMessage = (content) => {
  if (!content) return ''
  return content.replace(/\n/g, '<br>')
}

const sendMessage = async () => {
  if (!inputMessage.value.trim()) {
    ElMessage.warning('请输入内容')
    return
  }

  if (isStreaming.value) {
    ElMessage.warning('AI正在回复中，请稍候...')
    return
  }

  const userMessage = {
    role: 'user',
    content: inputMessage.value,
    time: new Date()
  }
  messages.value.push(userMessage)

  emit('send', {
    message: inputMessage.value,
    context: getContextMessages()
  })

  inputMessage.value = ''

  await nextTick()
  scrollToBottom()
}

const startStreaming = () => {
  isStreaming.value = true
  currentStreamContent.value = ''
}

const endStreaming = () => {
  isStreaming.value = false
  if (currentStreamContent.value) {
    const aiMessage = {
      role: 'assistant',
      content: currentStreamContent.value,
      time: new Date()
    }
    messages.value.push(aiMessage)
    currentStreamContent.value = ''
  }
}

// 终止AI对话
const emitAbort = () => {
  emit('abort')
  endStreaming()
  ElMessage.info('已终止AI对话')
}

const updateStreamContent = (content) => {
  if (content && content.length > currentStreamContent.value.length) {
    const newContent = content.slice(currentStreamContent.value.length)
    currentStreamContent.value = content
    nextTick(() => {
      scrollToBottom()
    })
  }
}

// 确认清空历史
const confirmClearHistory = () => {
  ElMessageBox.confirm('确定要清空所有对话历史吗？此操作不可恢复。', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    clearHistory()
    ElMessage.success('对话历史已清空')
  }).catch(() => {})
}

const addAiResponse = (content) => {
  if (typeof content === 'string') {
    const aiMessage = {
      role: 'assistant',
      content,
      time: new Date()
    }
    messages.value.push(aiMessage)
  } else if (content && typeof content === 'object') {
    if (content.isStreaming) {
      if (content.start) {
        startStreaming()
      } else if (content.end) {
        endStreaming()
        if (currentStreamContent.value) {
          const aiMessage = {
            role: 'assistant',
            content: currentStreamContent.value,
            time: new Date()
          }
          messages.value.push(aiMessage)
        }
      } else if (content.content) {
        currentStreamContent.value = content.content
        nextTick(() => {
          scrollToBottom()
        })
      }
    }
  }
  nextTick(() => {
    scrollToBottom()
  })
}

const scrollToBottom = () => {
  if (messagesRef.value) {
    messagesRef.value.scrollTop = messagesRef.value.scrollHeight
  }
}

watch(messages, () => {
  nextTick(() => {
    scrollToBottom()
  })
})

onMounted(() => {
  scrollToBottom()
})

const clearHistory = () => {
  messages.value = []
  currentStreamContent.value = ''
  isStreaming.value = false
}

// 处理上下文开关变化
const handleContextChange = (value) => {
  emit('context-change', value)
}

// 获取最后一条AI消息
const getLastAiMessage = () => {
  // 首先查找流式显示中的内容
  if (isStreaming.value && currentStreamContent.value) {
    return currentStreamContent.value
  }
  
  // 然后查找历史消息中最后一条AI消息
  for (let i = messages.value.length - 1; i >= 0; i--) {
    if (messages.value[i].role === 'assistant') {
      return messages.value[i].content
    }
  }
  
  return ''
}

defineExpose({
  addAiResponse,
  startStreaming,
  endStreaming,
  updateStreamContent,
  clearHistory,
  getContextMessages
})
</script>

<style lang="scss" scoped>
.novel-ai-chat {
  height: 100%;
  display: flex;
  flex-direction: column;
  background-color: #f9fafc;
  border-radius: 12px;
  overflow: hidden;
  max-height: 100%;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
  border: 1px solid rgba(214, 222, 235, 0.6);

  .chat-header {
    padding: 16px 20px;
    background: linear-gradient(90deg, #1a2236, #283454);
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    display: flex;
    justify-content: space-between;
    align-items: center;

    h3 {
      margin: 0;
      font-size: 18px;
      font-weight: 500;
      color: #ffffff;
      letter-spacing: 0.5px;
    }
    
    .chat-actions {
      display: flex;
      gap: 8px;
    }
  }

  .chat-messages {
    flex: 1;
    padding: 24px;
    overflow-y: auto;
    min-height: 200px;
    max-height: calc(100% - 160px);
    display: flex;
    flex-direction: column;
    gap: 20px;
    background: linear-gradient(135deg, #f9fafc, #f1f5fa);
    scroll-behavior: smooth;

    .message {
      max-width: 85%;
      margin-bottom: 4px;
      display: flex;
      gap: 12px;
      animation: fadeIn 0.3s ease-in;

      &.user-message {
        align-self: flex-end;
        flex-direction: row-reverse;
        
        .message-content {
          background: linear-gradient(135deg, #3b7df8, #5d93fa);
          color: #fff;
          border-radius: 18px 4px 18px 18px;
          box-shadow: 0 4px 12px rgba(59, 125, 248, 0.25);
        }
        
        .user-avatar {
          background-color: #3b7df8;
          color: white;
        }
      }

      &.ai-message {
        align-self: flex-start;
        
        .message-content {
          background: white;
          color: #1a2236;
          border-radius: 4px 18px 18px 18px;
          box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
          border: 1px solid rgba(214, 222, 235, 0.8);
        }
        
        .ai-avatar {
          background-color: #16a085;
          color: white;
        }
      }

      .message-content {
        padding: 14px 18px;
        flex: 1;

        .message-text {
          white-space: pre-wrap;
          word-break: break-word;
          line-height: 1.6;
          font-size: 15px;
        }

        .message-time {
          font-size: 12px;
          opacity: 0.7;
          margin-top: 6px;
          text-align: right;
        }
        
        .message-typing {
          padding: 4px 0;
          display: flex;
          gap: 4px;
          
          .typing-dot {
            width: 8px;
            height: 8px;
            background: #3b7df8;
            border-radius: 50%;
            display: inline-block;
            animation: typingAnimation 1.4s infinite ease-in-out both;
            
            &:nth-child(1) {
              animation-delay: -0.32s;
            }
            
            &:nth-child(2) {
              animation-delay: -0.16s;
            }
          }
        }
      }
    }
  }

  .chat-input {
    padding: 20px;
    background-color: white;
    border-top: 1px solid rgba(214, 222, 235, 0.8);
    flex-shrink: 0;

    :deep(.el-textarea__inner) {
      border-radius: 12px;
      border: 1px solid #dcdfe6;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
      padding: 12px 16px;
      font-size: 15px;
      transition: all 0.3s;
      
      &:focus {
        box-shadow: 0 2px 12px rgba(59, 125, 248, 0.15);
        border-color: #3b7df8;
      }
    }

    .input-actions {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-top: 16px;

      .left-actions {
        display: flex;
        align-items: center;
        gap: 12px;

        .help-icon {
          color: #606266;
          cursor: pointer;
          transition: color 0.3s;
          
          &:hover {
            color: #3b7df8;
          }
        }
      }

      .right-actions {
        display: flex;
        align-items: center;
        gap: 12px;

        .input-tip {
          font-size: 13px;
          color: #909399;
        }
      }
    }
  }
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes typingAnimation {
  0%, 80%, 100% { transform: scale(0.6); }
  40% { transform: scale(1); }
}
</style>
